#include "app_dev.h"

typedef struct
{

    bool is_running;

    buffer_handle_t down_buufer;
    buffer_handle_t up_buffer;

} device_t;

static device_t dev;

void mqtt_recv_cb(void *data, int len);

gate_state_t app_dev_init(void)
{
    // 1. mqtt初始化
    gate_state_t state = app_mqtt_init();
    if (state != GATE_OK)
    {
        log_fatal("mqtt init error");
        return GATE_ERROR;
    }
    app_mqtt_resister_revc_cb(mqtt_recv_cb);
    log_info("mqtt init ok");
    // 2. 线程池初始化
    state = app_pool_init(10);
    if (state != GATE_OK)
    {
        log_fatal("thread pool init error");
        app_mqtt_deinit();
        return GATE_ERROR;
    }
    log_info("thread pool init ok");

    // 3. 缓冲区初始化
    dev.down_buufer = app_buffer_init(1024);
    if (dev.down_buufer == NULL)
    {
        log_fatal("down buffer init error");
        app_pool_deinit();
        app_mqtt_deinit();
        return GATE_ERROR;
    }
    log_info("down buffer init ok");
    dev.up_buffer = app_buffer_init(1024);
    if (dev.up_buffer == NULL)
    {
        log_fatal("up buffer init error");
        app_buffer_deinit(dev.down_buufer);
        app_pool_deinit();
        app_mqtt_deinit();
        return GATE_ERROR;
    }
    log_info("up buffer init ok");

    // 4.modubs初始化 TODO
    state = app_modbus_init();
    if (state != GATE_OK)
    {
        log_fatal("modubs init error");
        app_buffer_deinit(dev.down_buufer);
        app_buffer_deinit(dev.up_buffer);
        app_pool_deinit();
        app_mqtt_deinit();
        return GATE_ERROR;
    }
    log_info("modubs init ok");

    log_info("dev init ok");

    return GATE_OK;
}

void app_up_task(void *);
void app_modubs_task(void *);

void app_dev_start(void)
{
    // 1. 添加上传数据的任务
    app_pool_add_task(app_up_task, NULL);
    app_pool_add_task(app_up_task, NULL);

    // 2. 添加modubs读写任务
    app_pool_add_task(app_modubs_task, NULL);
    app_pool_add_task(app_modubs_task, NULL);

    app_dev_set_is_running(true);
}

void app_dev_deinit(void)
{
    app_mqtt_deinit();
    app_pool_deinit();
    app_buffer_deinit(dev.down_buufer);
    app_buffer_deinit(dev.up_buffer);
}

void app_dev_stop(void)
{
    app_dev_set_is_running(false);
}

void app_up_task(void *args)
{
    char data[255];
    while (1)
    {
        int real_len = app_buffer_read(dev.up_buffer, data, sizeof(data));
        if (real_len > 0)
        {
            data[real_len] = '\0';
            app_mqtt_send(data, real_len);
        }
    }
}
void app_modubs_task(void *args)
{
    char data[255] = {0};
    while (1)
    {
        memset(data, 0, sizeof(data));
        int real_len = app_buffer_read(dev.down_buufer, data, sizeof(data));

        if (real_len == 0)
            continue;

        msg_t msg;
        json_2_msg(data, &msg);

        // 打印msg每个成员
        log_debug("action: %s, connetType: %s, motorId: %d, motorSpeed: %d, status: %s",
                  msg.action,
                  msg.connetType,
                  msg.motorId,
                  msg.motorSpeed,
                  msg.status);
        if (strcmp(msg.action, "set") == 0)
        {
            // 给modubs发送数据, 不需要接收
            app_modbus_write_single_holde_register(msg.motorId, (uint16_t)msg.motorSpeed);
        }
        else if (strcmp(msg.action, "get") == 0)
        {
            // 给modubs发送数据, 需要接收
            gate_state_t state = app_modbus_read_single_input_register(msg.motorId, (uint16_t *)&msg.motorSpeed);

            // 假设获取到了数据
            if (state == GATE_OK)
            {
                msg.status = "ok";
            }
            else
            {
                msg.status = "error";
                msg.motorSpeed = 0;
            }
            memset(data, 0, sizeof(data));
            msg_2_json(&msg, data);
            app_buffer_write(dev.up_buffer, data, (uint8_t)strlen(data));
        }
    }
}

void mqtt_recv_cb(void *data, int len)
{
    app_buffer_write(dev.down_buufer, data, len);
}

bool app_dev_get_is_running(void)
{
    return dev.is_running;
}

void app_dev_set_is_running(bool is_running)
{
    dev.is_running = is_running;
}
